package gameConfData

import (
	"github.com/TarsCloud/TarsGo/tars"
	"reflect"
	"sort"
)

type ConfType map[int32]interface{}

//////////////////////// 通用配置读取接口（mysql版【可用】） ////////////////////////////////

// 读取单个数据对象
// 参数1：配置实体对象类名
// 参数2：key: 必须是 int 或者 string 类型（例如传入int64，则查找不到实例）
// 返回：配置对象实例或者nil，类型为interface{}（需要判空）
// 调用demo：
//	confEntity := gameConfData.GetConfById("Equip", 1010404).(equipConfEntity.EquipConf)
func GetConfById(entityName string, key interface{}) interface{} {
	gameData := gameConf.GameData
	mapConfCtn, ok := gameData[entityName]
	if !ok {
		tars.TLOG.Errorf("GetConfById|【配置】：不存在配置表：%s", entityName)
		return nil
	}
	rwLock, ok2 := gameConf.RwLockData[entityName]
	if !ok2 {
		tars.TLOG.Errorf("GetConfById|【配置】：不存在读写锁：%s", entityName)
		return nil
	}
	rwLock.RLock()
	defer rwLock.RUnlock()
	entityConf, ok := mapConfCtn.(map[interface{}]interface{})[key]
	if !ok {
		tars.TLOG.Errorf("GetConfById|【配置%s】：不存在配置实例，key：%d", entityName, key)
		return nil
	}
	return entityConf
}

// 批量读取配置数据对象
// 参数1：配置实体对象类名
// 参数2：索引数组，数组元素必须是int或者string（可以传入多个ID获取多个配置对象）
// 返回：配置对象实例列表或者nil，类型为[]interface{}（需要判空）
// 调用demo：
//	confEntityList := gameConfData.GetBatchConfByIds("Equip", []int{1010404, 1010405})
//	for i := 0 ; i < len(confEntityList); i++ {
//		confEntity := confEntityList[i].(equipConfEntity.EquipConf)
//	}
func GetBatchConfByIds(entityName string, keys interface{}) []interface{} {
	gameData := gameConf.GameData
	_, ok := gameData[entityName]
	if !ok {
		tars.TLOG.Errorf("GetBatchConfByIds|【配置】：不存在配置表：%s", entityName)
		return nil
	}
	rfTyp := reflect.TypeOf(keys)
	if reflect.Slice != rfTyp.Kind() {
		tars.TLOG.Errorf("GetBatchConfByIds|【配置】：传入参数非法：%s", entityName)
		return nil
	}
	rfVal := reflect.ValueOf(keys)
	rwLock, ok2 := gameConf.RwLockData[entityName]
	if !ok2 {
		tars.TLOG.Errorf("GetBatchConfByIds|【配置】：不存在读写锁：%s", entityName)
		return nil
	}
	rwLock.RLock()
	defer rwLock.RUnlock()
	entityConfs := []interface{}{}
	for i := 0; i < rfVal.Len(); i++ {
		entityConf := GetConfById(entityName, rfVal.Index(i).Interface())
		if nil != entityConf {
			entityConfs = append(entityConfs, entityConf)
		}
	}
	return entityConfs
}

// 批量读取配置数据对象（特殊用法，传入从二级索引开始的数值，如：id2, id3的数值，去定位最终的的配置实例）
// 参数1：配置实体对象类名
// 参数2：索引数组，数组元素必须是int或者string类型（可以传入多个ID获取多个配置对象）
// 参数3：传入二级或者以上索引数值，获取到具体的配置实例（必须是int或string类型）
// 返回：配置对象实例列表或者nil，类型为[]interface{}（需要判空）
// 调用demo：获取的技能列表：id列表为heroSkillIds并且技能等级为1的技能
//	skillList_t := gameConfData.GetBatchConfByIds2("Skill", heroSkillIds, 1)
//	for _, skill_t := range skillList_t {
//		skill := skill_t.(skillConfEntity.SkillConfEntity)
//		.....
//	}
func GetBatchConfByIds2(entityName string, keys interface{}, key ...interface{}) []interface{} {
	gameData := gameConf.GameData
	_, ok := gameData[entityName]
	if !ok {
		tars.TLOG.Errorf("GetBatchConfByIds|【配置】：不存在配置表：%s", entityName)
		return nil
	}

	rfTyp := reflect.TypeOf(keys)
	if reflect.Slice != rfTyp.Kind() {
		tars.TLOG.Errorf("GetBatchConfByIds|【配置】：传入参数非法：%s", entityName)
	}
	rfVal := reflect.ValueOf(keys)
	rwLock, ok2 := gameConf.RwLockData[entityName]
	if !ok2 {
		tars.TLOG.Errorf("GetBatchConfByIds|【配置】：不存在读写锁：%s", entityName)
		return nil
	}
	rwLock.RLock()
	defer rwLock.RUnlock()

	entityConfs := []interface{}{}
	for i := 0; i < rfVal.Len(); i++ {
		entityConf := GetConfById(entityName, rfVal.Index(i).Interface())
		if nil != entityConf {
			_, ok := entityConf.(map[interface{}]interface{}) // 判断是否有二级map，通过尝试类型转化是否成功判断
			if ok { // 多行row实例的情况
				for j := 0; j < len(key); j++ {
					_, ok = entityConf.(map[interface{}]interface{})
					if ok {
						entityConf, _ = entityConf.(map[interface{}]interface{})[key[j]]
						if nil == entityConf {
							tars.TLOG.Errorf("GetBatchConfByIds2|【配置%s】：不存在，key1:%d, keyN：%d",
								entityName, rfVal.Index(i).Interface(), key[j])
							break
						}
					} else {
						break
					}
				}
				if nil != entityConf { // 转到单个row实例才跳出上述循环，append到entityConfs列表
					entityConfs = append(entityConfs, entityConf)
				}
			} else { // 已经是单行row实例的情况
				entityConfs = append(entityConfs, entityConf)
			}
		}
	}
	return entityConfs
}

// 获取多级索引配置
// 参数1：配置实体对象类名
// 参数n：不定参数，必须是int或者string类型（支持多级ID索引查找指定对象）
// 返回：配置对象实例/实例列表/nil，类型为interface{}或[]interface{}（需要判空）
// 调用demo（获取单个）：
//	confEntity := gameConfData.GetConfByMultiIds("EquipStrengthen", 40100101, 1)
//	if nil != confEntity {
//		entity := confEntity.(equipConfEntity.EquipConf)
//		tars.TLOG.Debugf(">>>>>>>>>> entity=%+v", entity)
//	}
// 调用demo（获取一组数据）：
// confEntityList := gameConfData.GetConfByMultiIds("EquipStrengthen", 40100101)
// if nil != confEntityList {
//		confEntityList_t := confEntityList.(map[int]equipConfEntity.EquipConf)
//		..... do something ....
// }
func GetConfByMultiIds(entityName string, key ...interface{}) interface{} {
	gameData := gameConf.GameData
	mapConfCtn, ok := gameData[entityName]
	if !ok {
		tars.TLOG.Errorf("GetConfByMultiIds|【配置】：不存在配置表：%s", entityName)
		return nil
	}

	rwLock, ok2 := gameConf.RwLockData[entityName]
	if !ok2 {
		tars.TLOG.Errorf("GetConfByMultiIds|【配置】：不存在读写锁：%s", entityName)
		return nil
	}
	rwLock.RLock()
	defer rwLock.RUnlock()

	entityConf := mapConfCtn
	for i := 0; i < len(key); i++ {
		entityConf, _ = entityConf.(map[interface{}]interface{})[key[i]]
		if nil == entityConf {
			tars.TLOG.Errorf("GetConfByMultiIds|【配置%s】：不存在配置实例，key：%d", entityName, key[i])
			return nil
		}
	}
	return entityConf
}

// 通过实体名字获取对应的所有配置实例
func GetAllConfByName(entityName string) map[interface{}]interface{} {
	gameData := gameConf.GameData
	mapConfCtn, ok := gameData[entityName]
	if !ok {
		tars.TLOG.Errorf("GetAllConf|【配置】：不存在配置表：%s", entityName)
		return nil
	}

	rwLock, ok2 := gameConf.RwLockData[entityName]
	if !ok2 {
		tars.TLOG.Errorf("GetAllConf|【配置】：不存在读写锁：%s", entityName)
		return nil
	}
	rwLock.RLock()
	defer rwLock.RUnlock()

	return mapConfCtn.(map[interface{}]interface{})
}

// 获取指定层级后的已排序id列表 (仅支持id为int的情况，不支持string的情况)
// desc：指定是否降序
// key：如果指定key，key必须是int或string类型
func GetAllKeySorted(entityName string, desc bool, key ...interface{}) []int {
	gameData := gameConf.GameData
	mapConfCtn, ok := gameData[entityName]
	if !ok {
		tars.TLOG.Errorf("GetAllKeySorted|【配置】：不存在配置表：%s", entityName)
		return nil
	}

	rwLock, ok2 := gameConf.RwLockData[entityName]
	if !ok2 {
		tars.TLOG.Errorf("GetAllKeySorted|【配置】：不存在读写锁：%s", entityName)
		return nil
	}
	rwLock.RLock()
	defer rwLock.RUnlock()

	result := []int{}
	entityConf := mapConfCtn
	for i := 0; i < len(key); i++ {
		entityConf, _ = entityConf.(map[interface{}]interface{})[key[i]]
		if nil == entityConf {
			tars.TLOG.Errorf("GetConfByMultiIds|【配置%s】：不存在配置实例，key：%d", entityName, key[i])
			return nil
		}
	}

	for id, _ := range entityConf.(map[interface{}]interface{}) {
		result = append(result, id.(int))
	}
	if desc {
		sort.Slice(result, func (i, j int) bool {
			return result[i] > result[j]
		})
	} else {
		sort.Ints(result)
	}
	return result
}